#ifndef _MALLOC_H
#define _MALLOC_H 

#include <types.h>
#include <list.h>
#include <memory.h>

#define MAF_SDRAM		(0)
#define MAF_SRAM		(1)
#define MAF_DMA			(2)
#define MAF_TYPE_MASK	(3)

#define maf_is_sdram(flags)		(((flags) & MAF_TYPE_MASK) == MAF_SDRAM)
#define maf_is_sram(flags)		(((flags) & MAF_TYPE_MASK) == MAF_SRAM)
#define maf_is_dma(flags)		(((flags) & MAF_TYPE_MASK) == MAF_DMA)

struct memory_zone;

struct memory_allocator {
	char *name;
	struct list_head n_allocator_list;
	int (*startup)(struct memory_zone *zone);
	void *(*malloc)(struct memory_zone *zone, size_t bytes);
	void (*free)(struct memory_zone *zone, void* mem);
	void *(*calloc)(struct memory_zone *zone, size_t n_elements, size_t elem_size);
	void *(*realloc)(struct memory_zone *zone, void* mem, size_t newsize);
	void *(*realloc_in_place)(struct memory_zone *zone, void* mem, size_t newsize);
	void *(*memalign)(struct memory_zone *zone, size_t alignment, size_t bytes);
	size_t (*footprint)(struct memory_zone *zone);
	size_t (*max_footprint)(struct memory_zone *zone);
	size_t (*footprint_limit)(struct memory_zone *zone);
};

extern struct memory_allocator *default_memory_allocator;

void *kalloc(struct memory_zone *zone, int size);

int memory_allocator_add(struct memory_allocator *allocator);
struct memory_allocator *memory_allocator_get(char *name);

void *kmalloc(size_t bytes, unsigned int flags);
void kfree(void* mem);
void *kcalloc(size_t n_elements, size_t elem_size, unsigned int flags);
void *krealloc(void* mem, size_t newsize);
void *krealloc_in_place(void* mem, size_t newsize);
void *kmemalign(size_t alignment, size_t bytes, unsigned int flags);
size_t kmalloc_footprint(void); 
size_t kmalloc_max_footprint(void);
size_t kmalloc_footprint_limit(void);

#endif /* _MALLOC_H */

